package socketmvc.core.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class JsonKit {
    private static final Logger log = LoggerFactory.getLogger(JsonKit.class);

    private static final SerializeConfig mapping = new SerializeConfig();

    static {
        mapping.put(Date.class, new SimpleDateFormatSerializer("yyyy-MM-dd HH:mm:ss"));
        mapping.put(java.sql.Date.class, new SimpleDateFormatSerializer("yyyy-MM-dd HH:mm:ss"));
        mapping.put(java.sql.Timestamp.class, new SimpleDateFormatSerializer("yyyy-MM-dd HH:mm:ss"));
        mapping.put(java.sql.Time.class, new SimpleDateFormatSerializer("HH:mm:ss"));
        mapping.put(java.lang.Long.class, new ToStringSerializer());
    }

    public static SerializeConfig put(Class<?> clazz, SerializeFilter filter) {
        mapping.addFilter(clazz, filter);
        return mapping;
    }

    public static SerializeConfig put(Class<?> clazz, ObjectSerializer serializer) {
        mapping.put(clazz, serializer);
        return mapping;
    }

    public static <T> T toBean(String jsonStr, Class<T> tClass) {
        if (jsonStr == null || jsonStr.isBlank()) {
            return null;
        }
        try {
            return JSON.parseObject(jsonStr, tClass);
        } catch (Throwable e) {
            log.error("json解析失败:\r\n{}", jsonStr);
            throw new RuntimeException(e);
        }
    }

    public static <T> T toBean(String jsonStr, Type type) {
        if (jsonStr == null || jsonStr.isBlank()) {
            return null;
        }
        try {
            return JSON.parseObject(jsonStr, type);
        } catch (Throwable e) {
            log.error("json解析失败:\r\n{}", jsonStr);
            throw new RuntimeException(e);
        }
    }

    public static <T> T toBean(byte[] bytes, Class<T> tClass) {
        try {
            if (bytes == null) {
                return null;
            }

            return JSON.parseObject(bytes, tClass);
        } catch (Throwable e) {
            log.error("json解析失败:\r\n{}", bytes);
            throw new RuntimeException(e);
        }
    }

    public static String toFormattedJson(Object bean) {
        try {
            return JSON.toJSONString(bean, mapping, SerializerFeature.DisableCircularReferenceDetect, SerializerFeature.PrettyFormat);
        } catch (Throwable e) {
            throw new RuntimeException(e);
        }
    }

    public static String toJSONEnumNoUsingName(Object bean){
        int features=SerializerFeature.config(JSON.DEFAULT_GENERATE_FEATURE, SerializerFeature.WriteEnumUsingName, false);
        return JSONObject.toJSONString(bean,features);
    }

    public static String toJSONString(Object bean,SerializerFeature serializerFeature){
        return JSONObject.toJSONString(bean,mapping,serializerFeature);
    }

    public static String toJSONString(Object bean) {
        try {
            return JSON.toJSONString(bean, mapping, SerializerFeature.DisableCircularReferenceDetect);
        } catch (Throwable e) {
            throw new RuntimeException(e);
        }
    }

    public static String toJSONString(Object bean, SerializeFilter serializeFilter) {
        try {
            if (serializeFilter != null) {
                return JSON.toJSONString(bean, mapping, serializeFilter, SerializerFeature.DisableCircularReferenceDetect);
            } else {
                return JSON.toJSONString(bean, mapping, SerializerFeature.DisableCircularReferenceDetect);
            }

        } catch (Throwable e) {
            throw new RuntimeException(e);
        }
    }

    public static byte[] toJsonBytes(Object bean) {
        return JSON.toJSONBytes(bean, mapping, SerializerFeature.DisableCircularReferenceDetect);
    }

    public static byte[] toJSONBytesEnumNoUsingName(Object bean){
        int features=SerializerFeature.config(JSON.DEFAULT_GENERATE_FEATURE, SerializerFeature.WriteEnumUsingName, false);
        return JSONObject.toJSONBytes(bean,features);
    }

    /**
     * 成指定类型集合;
     * @param data
     * @param clazz
     * @return
     */
    public static <T> List<T> toArray(List<String> data, Class<T> clazz){
        if(data == null) {
            return null;
        }
        List<T> result  = new ArrayList<T>();
        for(String obj : data){
            result.add(toBean(obj, clazz));
        }
        return result;
    }
}
